#include "halcon_opencv.h"
Mat himageToMat(HObject& imgHalcon)
{
    if (!imgHalcon.IsInitialized())
    {
        return Mat(100, 100, CV_8UC3);
    }
    HTuple hv_n;
    HObject empty;
    GenEmptyObj(&empty);
    TestEqualObj(imgHalcon, empty, &hv_n);
    if (hv_n == 1) //两个Obj相等
    {
        return Mat(100, 100, CV_8UC3);
    }

    HTuple channels;
    HString cType;
    cv::Mat Image;
    ConvertImageType(imgHalcon, &imgHalcon, "byte");
    CountChannels(imgHalcon, &channels);
    Hlong width = 0;
    Hlong height = 0;
    if (channels[0].I() == 1)
    {
        HImage hImg(imgHalcon);
        void* ptr = hImg.GetImagePointer1(&cType, &width, &height);//GetImagePointer1(Hobj, &ptr, &cType, &wid, &hgt);
        int W = width;
        int H = height;
        Image.create(H, W, CV_8UC1);
        unsigned char* pdata = static_cast<unsigned char*>(ptr);
        memcpy(Image.data, pdata, W * H);
    }
    else if (channels[0].I() == 3)
    {
        void* Rptr;
        void* Gptr;
        void* Bptr;
        HImage hImg(imgHalcon);
        hImg.GetImagePointer3(&Rptr, &Gptr, &Bptr, &cType, &width, &height);
        int W = width;
        int H = height;
        Image.create(H, W, CV_8UC3);
        std::vector<cv::Mat> VecM(3);
        VecM[0].create(H, W, CV_8UC1);
        VecM[1].create(H, W, CV_8UC1);
        VecM[2].create(H, W, CV_8UC1);
        unsigned char* R = (unsigned char*)Rptr;
        unsigned char* G = (unsigned char*)Gptr;
        unsigned char* B = (unsigned char*)Bptr;
        memcpy(VecM[2].data, R, W * H);
        memcpy(VecM[1].data, G, W * H);
        memcpy(VecM[0].data, B, W * H);
        cv::merge(VecM, Image);
    }
    return Image;
}

//Halcon HObjectתOpenCV Mat
HObject matToHImage( Mat& imgMat)
{
    HObject Hobj = HObject();
    int height = imgMat.rows;
    int width = imgMat.cols;
    //  CV_8UC3
    if (imgMat.type() == CV_8UC3)
    {
        std::vector<cv::Mat> vec;
        cv::split(imgMat, vec);

        cv::Mat imgB = vec[0];
        cv::Mat imgG = vec[1];
        cv::Mat imgR = vec[2];

        HalconCpp::HObject himgR,himgG,himgB;
        GenImage1(&himgR, "byte", width, height, (Hlong)imgR.data);
        GenImage1(&himgG, "byte", width, height, (Hlong)imgG.data);
        GenImage1(&himgB, "byte", width, height, (Hlong)imgB.data);
        HalconCpp::Compose3(himgR, himgG, himgB, &Hobj);
    }
    //  CV_8UCU1
    else if (imgMat.type() == CV_8UC1)
    {
        GenImage1(&Hobj, "byte", width, height, (Hlong)imgMat.data);
    }
    return Hobj;
}

Mat drawRegionFill( Mat mat_image, HObject region, Scalar color)
{
    if (!region.IsInitialized())
    {
        return mat_image;
    }
    HTuple hv_n;
    HObject empty;
    GenEmptyObj(&empty);
    TestEqualObj(region, empty, &hv_n);
    if (hv_n == 1) //两个Obj相等
    {
        return mat_image;
    }

    std::vector<std::vector<Point>> vector_vector_contour;
    HTuple hv_Length;
    HObject xlds;
    GenContourRegionXld(region, &xlds, "border");
    CountObj(xlds, &hv_Length);
    int region_number = hv_Length[0].I();
    for (int j = 1; j <= region_number; j++)
    {
        std::vector<Point> vector_contour;
        HObject xld;
        HTuple HTuplerow, HTuplecolumn, HTuplelength;
        SelectObj(xlds, &xld, j);

        GetContourXld(xld, &HTuplerow, &HTuplecolumn);
        TupleLength(HTuplerow, &HTuplelength);
        int xld_number = HTuplelength[0].I();
        for (int m = 0; m < xld_number; m++)
        {
            Point point;
            point.y = HTuplerow[m].D();
            point.x = HTuplecolumn[m].D();
            vector_contour.push_back(point);
        }
        vector_vector_contour.push_back(vector_contour);
    }
    Mat mat_out = mat_image.clone();
    drawContours(mat_out, vector_vector_contour, -1, color, -1);
    return mat_out;
}

Mat drawRegion( Mat mat_image, HObject region, Scalar color)
{
    if (!region.IsInitialized())
    {
        return mat_image;
    }
    HTuple hv_n;
    HObject empty;
    GenEmptyObj(&empty);
    TestEqualObj(region, empty, &hv_n);
    if (hv_n == 1) //两个Obj相等
    {
        return mat_image;
    }

    std::vector<std::vector<Point>> vector_vector_contour;
    HTuple hv_Length;
    HObject xlds;
    GenContourRegionXld(region, &xlds, "border");
    CountObj(xlds, &hv_Length);
    int region_number = hv_Length[0].I();
    for (int j = 1; j <= region_number; j++)
    {
        std::vector<Point> vector_contour;
        HObject xld;
        HTuple HTuplerow, HTuplecolumn, HTuplelength;
        SelectObj(xlds, &xld, j);

        GetContourXld(xld, &HTuplerow, &HTuplecolumn);
        TupleLength(HTuplerow, &HTuplelength);
        int xld_number = HTuplelength[0].I();
        for (int m = 0; m < xld_number; m++)
        {
            Point point;
            point.y = HTuplerow[m].D();
            point.x = HTuplecolumn[m].D();
            vector_contour.push_back(point);
        }
        vector_vector_contour.push_back(vector_contour);
    }
    Mat mat_out = mat_image.clone();
    drawContours(mat_out, vector_vector_contour, -1, color, 1);
    return mat_out;
}



void HObjectToQImage(HObject himage,QImage& qimage)
{
    HTuple hChannels;
    HTuple   width,height;
    width=height=0;
    HTuple htype;
    HTuple hpointer;

    ConvertImageType(himage,&himage,"byte");//将图片转化成byte类型
    CountChannels(himage,&hChannels);       //判断图像通道数

    if(hChannels[0].I()==1)//单通道图
    {
        unsigned char *ptr;

        GetImagePointer1(himage,&hpointer,&htype,&width,&height);

        ptr=(unsigned char *)hpointer[0].L();
        qimage =QImage(ptr,width,height,width,QImage::Format_Indexed8);//不知道是否已自动4字节对齐
    }
    else if(hChannels[0].I()==3)//三通道图
    {
//        unsigned char *ptr3;
//        HObject ho_ImageInterleaved;
//        rgb3_to_interleaved(himage, &ho_ImageInterleaved);

//        GetImagePointer1(ho_ImageInterleaved, &hpointer, &htype, &width, &height);

//        ptr3=(unsigned char *)hpointer[0].L();
//        qimage =QImage(ptr3,width/3,height,width,QImage::Format_RGB888);

        HObject imageInterleaved;
        // transform buffer to format used in Qt
        InterleaveChannels(himage,&imageInterleaved,"argb", "match",0);
        // get access to raw image data
        HTuple  pointer,type, width, height;
        GetImagePointer1(imageInterleaved,&pointer,&type, &width,&height);
        // create QImage from data
        qimage =  QImage((unsigned char *)pointer[0].L(), width[0].I() / 4, height[0].I(), QImage::Format_RGB32);

    }
}


void SSM (HObject ho_image, HObject *ho_region_error, HTuple hv_row1, HTuple hv_column1,
    HTuple hv_row2, HTuple hv_column2, HTuple hv_rgb_hsv, HTuple hv_channel1low,
    HTuple hv_channel1high, HTuple hv_channel2_low, HTuple hv_channel2_high, HTuple hv_channel3_low,
    HTuple hv_channel3_high, HTuple hv_no_yes_mask, HTuple hv_mask_character, HTuple *hv_ret,
    HTuple *hv_size_error)
{

  // Local iconic variables
  HObject  ho_Rectangle, ho_ImageReduced, ho_Image1;
  HObject  ho_Image2, ho_Image3, ho_Region1, ho_Region2, ho_Region12;
  HObject  ho_Region3, ho_GrayImage, ho_RegionG, ho_RegionDilation;

  // Local control variables
  HTuple  hv_Row, hv_Column;


  GenRectangle1(&ho_Rectangle, hv_row1, hv_column1, hv_row2, hv_column2);
  ReduceDomain(ho_image, ho_Rectangle, &ho_ImageReduced);

  Decompose3(ho_ImageReduced, &ho_Image1, &ho_Image2, &ho_Image3);
  if (0 != (int(hv_rgb_hsv==1)))
  {
    TransFromRgb(ho_Image1, ho_Image2, ho_Image3, &ho_Image1, &ho_Image2, &ho_Image3,
        "hsv");
  }


  Threshold(ho_Image1, &ho_Region1, hv_channel1low, hv_channel1high);


  Threshold(ho_Image2, &ho_Region2, hv_channel2_low, hv_channel2_high);

  Intersection(ho_Region1, ho_Region2, &ho_Region12);

  Threshold(ho_Image3, &ho_Region3, hv_channel3_low, hv_channel3_high);

  Intersection(ho_Region12, ho_Region3, &(*ho_region_error));



  if (0 != (int(hv_no_yes_mask>0)))
  {
    Rgb1ToGray(ho_ImageReduced, &ho_GrayImage);
    Threshold(ho_GrayImage, &ho_RegionG, hv_mask_character, "max");
    DilationRectangle1(ho_RegionG, &ho_RegionDilation, 9, 9);
    Difference((*ho_region_error), ho_RegionDilation, &(*ho_region_error));
  }

  AreaCenter((*ho_region_error), &(*hv_size_error), &hv_Row, &hv_Column);
  (*hv_ret) = 1;
  return;
}


